package com.tuzhi.base.web.util;

import com.tuzhi.common.exception.BaseRuntimeException;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

/**
 * 功能说明：
 *
 * @author abu
 * @version 1.1.0
 * @date 2023/3/8
 */

public class TZFileUtils {
    static Long MAX_SIZE = 1024l * 1024l * 1000;
    static Logger log = LoggerFactory.getLogger(TZFileUtils.class);

    /**
     * 上传文件 到服务器
     *
     * @param multipartFile  文件信息
     * @param savePath       保存的文件路径
     * @param reName         如果重命名，指定了 customFileName 不为空，用customFileName，为空，生成UUID 的名
     * @param customFileName 调用者指定文件名， ,且此字段不为空
     * @return
     */
    public static String uploadFile(MultipartFile multipartFile, String savePath, boolean reName, String customFileName, Long maxSize) {
        maxSize = maxSize == null ? MAX_SIZE : maxSize;
        try {
            String originalFilename = multipartFile.getOriginalFilename();
            // 文件名非空校验
            if (StringUtils.isEmpty(originalFilename)) {
                throw new BaseRuntimeException("文件名不能为空");
            }
            // 大文件判定
            if (multipartFile.getSize() > maxSize) {
                throw new BaseRuntimeException("文件过大，请使用大文件传输");
            }
            // 生成新文件名
            String newName = originalFilename;
            if (reName) {
                if (StringUtils.isNotEmpty(customFileName)) {
                    newName = customFileName;
                } else {
                    newName = uuid() + "_" + originalFilename;
                }

            }
            if (originalFilename.length() > 500) {
                throw new BaseRuntimeException(originalFilename + "文件名超长 500");
            }
            if (newName.length() > 500) {
                throw new BaseRuntimeException(newName + "文件名超长 500");
            }
            if (savePath.length() > 500) {
                throw new BaseRuntimeException(savePath + "文件保存目录超长 500");
            }

            // 重命名文件
            File newFile = new File(savePath, newName);
            // 如果该存储路径不存在则新建存储路径
            if (!newFile.getParentFile().exists()) {
                newFile.getParentFile().mkdirs();
            }
            // 文件写入
            multipartFile.transferTo(newFile);
            return newName;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseRuntimeException("上传协议文件出错:" + e.getMessage());
        }
    }

    public static String uuid() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public static String convertToFileName(HttpServletRequest request, String fileName) throws UnsupportedEncodingException {
        // 针对IE或者以IE为内核的浏览器：
        String userAgent = request.getHeader("User-Agent");
        if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
            fileName = URLEncoder.encode(fileName, "UTF-8");
        } else {
            // 非IE浏览器的处理：  
            fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
        }
        return fileName;
    }

    /**
     * 下载文件
     *
     * @param downFilePath 服务器的文件物理全路径
     * @param fileName     下载时的文件名，如果不指定，则取原文件名
     * @param request
     * @param response
     */
    public static boolean downFile(String downFilePath, String fileName, HttpServletRequest request, HttpServletResponse response,
                                   boolean estimateExits) {
        OutputStream outputStream = null;
        InputStream inputStream = null;
        try {
            File file = new File(downFilePath);
            if (estimateExits && !file.exists()) {
                return false;
            }
            String downFileName = fileName;
            if (StringUtils.isEmpty(downFileName)) {
                downFileName = FilenameUtils.getName(downFilePath);
            }
            inputStream = new FileInputStream(file);
            response.setHeader("Content-Disposition", "attachment;filename=" + TZFileUtils.convertToFileName(request, downFileName));
            // 获取输出流
            outputStream = response.getOutputStream();
            IOUtils.copy(inputStream, outputStream);
            return true;
        } catch (IOException e) {
//            System.out.println("文件下载出错");
//            e.printStackTrace();
            log.error("文件下载出错", e);
            return true;
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {

            }
        }
    }

    /**
     * 下载文件
     *
     * @param downFilePath 服务器的文件物理全路径
     * @param fileName     下载时的文件名，如果不指定，则取原文件名
     * @param inputStream
     * @param response
     */
    public static void downFile(String downFilePath, String fileName, HttpServletRequest request, HttpServletResponse response
            , InputStream inputStream) {
        OutputStream outputStream = null;
        try {
            if (StringUtils.isEmpty(fileName)) {
                fileName = FilenameUtils.getName(downFilePath);
            }
            response.setHeader("Content-Disposition", "attachment;filename=" + TZFileUtils.convertToFileName(request, fileName));
            // 获取输出流
            outputStream = response.getOutputStream();
            IOUtils.copy(inputStream, outputStream);
        } catch (IOException e) {
//            System.out.println("文件下载出错");
//            e.printStackTrace();
            log.error("文件下载出错", e);
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {

            }
        }
    }
}
